﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Caching;

namespace IloveRSS.Models.DataMap
{
    public class ChannelsMapRepository
    {
        private ILoveRSSDataContext dataContext;

        public ChannelsMapRepository(ILoveRSSDataContext dt)
        {
            this.dataContext = dt;
        }

        public Channels Add(String channelName, bool visible)
        {
            var channel = new Channels { ChannelName = channelName, Visible = visible, Rate = 0};
            dataContext.Channels.InsertOnSubmit(channel);
            dataContext.SubmitChanges();    
            return channel;
        }

        public IEnumerable<Tags> GetTags(int channelID)
        {
            return dataContext.Channels_Tags.Where(item => item.ChannelID == channelID).Select(item => item.Tags);
        }

        public IEnumerable<Sites> GetSites(int channelID)
        {
            return dataContext.Channels_Sites.Where(item => item.ChannelID == channelID).Select(item => item.Sites);
        }

        public String GetDescription(int channelID)
        {
            Channels channel = dataContext.Channels.FirstOrDefault(item => item.ID == channelID);
            if(null != channel)
            {
                return channel.Description;
            }
            else
            {
                //it exception
                return null;
            }
        }

        public int GetRate(int channelID)
        {
            Channels channel = dataContext.Channels.FirstOrDefault(item => item.ID == channelID);
            if(null != channel)
            {
                return channel.Rate ?? 0;
            }
            else
            {
                // it exception
                return -1;
            }
        }

        public Channels GetChannelByID(int channelId)
        {
            return dataContext.Channels.FirstOrDefault(item => item.ID == channelId);
        }

        public IEnumerable<Channels> GetChannelsByTags(List<string> tags)
        {
            var channels = dataContext.Channels;
            var multiDictionary = FindMatchTags(channels, tags);
            var channelResult = new List<Channels>();
            var collectionListChannel = multiDictionary.OrderByDescending(item => item.Key).Select(item => item.Value).ToList();
            foreach(var listChannel in collectionListChannel)
            {
                channelResult.AddRange(listChannel);
            }
            return channelResult;
        }

        private SortedDictionary<int, List<Channels>> FindMatchTags(IEnumerable<Channels> channels, List<string> tags)
        {
            var dictionary = new SortedDictionary<int, List<Channels>>();
            var channelList = new List<Channels>();
            
            foreach (var channel in channels)
            {
                int matchNumber = MatchTags(channel, tags);
                if(dictionary.ContainsKey(matchNumber))
                {
                    dictionary[matchNumber].Add(channel);
                }
                else
                {
                    channelList = new List<Channels>();
                    channelList.Add(channel);
                    dictionary.Add(matchNumber, channelList);
                }
            }
            return dictionary;
        }
         
        private int MatchTags(Channels channel, List<String> tags)
        {
            int matchNumber = 0;
            foreach (var tag in tags)
            {
                //matchNumber += channel.Tags.Where(item => item.Text.Trim().Equals(tag, StringComparison.OrdinalIgnoreCase)).Count();
                matchNumber += channel.Tags.Where(item => item.Text.Trim().StartsWith(tag, StringComparison.OrdinalIgnoreCase) || tag.StartsWith(item.Text.Trim(), StringComparison.OrdinalIgnoreCase)).Count();
            }
            return matchNumber;
        }

        public IEnumerable<Channels> GetChannelsByRate()
        {
            return dataContext.Channels.OrderByDescending(channel => channel.Rate);
        }
    }
}